package com.googlecode.yatspec.parsing;

import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.lang.String.format;

public class ScalaClass {
    private String source;

    public ScalaClass(URL url) {
        source = sourceFor(url);
    }

    private String sourceFor(URL url) {
        BufferedReader bufferedReader = null;
        try {
            bufferedReader = new BufferedReader(new FileReader(new File(url.toURI())));
            String line;
            StringWriter stringWriter = new StringWriter();
            while ((line = bufferedReader.readLine()) != null) {
                stringWriter.write(line);
                stringWriter.write(System.getProperty("line.separator"));
            }
            return stringWriter.toString();
        } catch (Exception e) {
            throw new RuntimeException(format("Cannot load Scala source from [%s]", url));
        } finally {
            if (null != bufferedReader) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    // ignore
                }
            }
        }
    }

    public Iterable<ScalaMethod> getTestMethods() {
        List<ScalaMethod> scalaMethods = new ArrayList<ScalaMethod>();
        Pattern pattern = Pattern.compile("@Test" +
                someWhiteSpace() +
                "def" + someWhiteSpace() + methodName() + emptyParameters() + someWhiteSpace() + openingBrace() +
                methodBody() +
                closingBrace(), Pattern.DOTALL | Pattern.MULTILINE);
        Matcher matcher = pattern.matcher(source);
        while (matcher.find()) {
            String methodName = matcher.group(1);
            String methodBody = matcher.group(2);
            scalaMethods.add(new ScalaMethod(methodName, methodBody));
        }
        return scalaMethods;
    }

    private String closingBrace() {
        return "\\}";
    }

    private String openingBrace() {
        return "\\{";
    }

    private String methodBody() {
        return "([^\\{]*)";
    }

    private String emptyParameters() {
        return "\\(\\)";
    }

    private String methodName() {
        return "(\\w+)";
    }

    private String someWhiteSpace() {
        return "\\s+";
    }
}
